home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / prof / profProfil.c < prev   
C/C++ Source or Header  |  1992-12-18  |  7KB  |  292 lines

  1. /* 
  2.  * profProfil.c --
  3.  *
  4.  *    Profil system call.
  5.  *
  6.  * Copyright 1989 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/prof/profProfil.c,v 9.5 92/01/08 01:14:43 shirriff Exp $";
  18. #endif /* not lint */
  19.  
  20. #include <assert.h>
  21. #include "sprite.h"
  22. #include "proc.h"
  23. #include "prof.h"
  24. #include "sync.h"
  25. #include "vm.h"
  26.  
  27. /*
  28.  * Program counter recorded by the interrupt handler.
  29.  */
  30. /* int Prof_InterruptPC; */
  31.  
  32. /*
  33.  * Monitor lock for this module.
  34.  */
  35. #ifndef lint
  36. static Sync_Lock profilLock = Sync_LockInitStatic("Prof:profilLock");
  37. #else
  38. static Sync_Lock profilLock;
  39. #endif
  40. #define LOCKPTR &profilLock
  41.  
  42. static void tick _ARGS_((Timer_Ticks time, ClientData clientData));
  43.  
  44. /*
  45.  * Information that is passed to Timer_ScheduleRoutine() to
  46.  * queue tick() for invocation by the call back timer
  47.  * interrupt handler.
  48.  */
  49. Timer_QueueElement profTimer_QueueElement = {
  50.     { NULL, NULL }, /* links */
  51.     tick,           /* routine */
  52.     0,              /* time */
  53.     1234,           /* clientData */
  54.     FALSE,          /* processed */
  55.     0               /* interval */
  56. };
  57.  
  58. /*
  59.  * Count of the number of processes being profiled.
  60.  */
  61. static int profCount = 0;
  62.  
  63.  
  64. /*
  65.  *----------------------------------------------------------------------
  66.  *
  67.  * profProfil --
  68.  *
  69.  *    Profil system call.
  70.  *
  71.  * Results:
  72.  *      Always returns success.
  73.  *
  74.  * Side effects:
  75.  *    Same as Prof_Enable.
  76.  *
  77.  *----------------------------------------------------------------------
  78.  */
  79.  
  80. ReturnStatus
  81. Prof_Profil(buffer, bufSize, offset, scale)
  82.     short *buffer;
  83.     int bufSize;
  84.     int offset;
  85.     int scale;
  86. {
  87.     Prof_Enable(Proc_GetCurrentProc(), buffer, bufSize, offset, scale);
  88.     return SUCCESS;
  89. }
  90.  
  91.  
  92. /*
  93.  *----------------------------------------------------------------------
  94.  *
  95.  * Prof_Enable --
  96.  *
  97.  *      Enables or disables the profiling of a process.
  98.  *
  99.  * Results:
  100.  *    None.
  101.  *
  102.  * Side effects:
  103.  *      Changes the Profiling fields in the Proc_ControlBlock, increments
  104.  *      or decrements ProfCount, and schedules or deschedules tick()
  105.  *      in the call back queue.
  106.  *
  107.  *----------------------------------------------------------------------
  108.  */
  109.  
  110. void
  111. Prof_Enable(procPtr, buffer, bufSize, offset, scale)
  112.     Proc_ControlBlock *procPtr;
  113.     short *buffer;
  114.     int bufSize;
  115.     int offset;
  116.     int scale;
  117. {
  118.  
  119.     assert(procPtr != (Proc_ControlBlock *) NIL);
  120.     LOCK_MONITOR;
  121.     if (scale != 0 && scale != 1 && procPtr->Prof_Scale == 0) {
  122.     /*
  123.      * If the profile routine has not already been scheduled for invocation
  124.      * by the call back timer, then schedule it.
  125.      */
  126.     if (profCount == 0) {
  127.         profTimer_QueueElement.interval = 20 * timer_IntOneMillisecond;
  128.         Timer_ScheduleRoutine(&profTimer_QueueElement, TRUE);
  129.     }
  130.     ++profCount;
  131.     } else if ((scale == 0 || scale == 1) && procPtr->Prof_Scale != 0) {
  132.     assert(profCount > 0);
  133.     /*
  134.      * Disable profiling.  If there are no other processes being profiled,
  135.      * then remove tick() from the call back queue.
  136.      */
  137.     --profCount;
  138.     if (profCount == 0) {
  139.         Timer_DescheduleRoutine(&profTimer_QueueElement);
  140.     }
  141.     }
  142.     procPtr->Prof_Buffer = buffer;
  143.     procPtr->Prof_BufferSize = bufSize;
  144.     procPtr->Prof_Offset = offset;
  145.     procPtr->Prof_Scale = scale;
  146.     procPtr->Prof_PC = 0;
  147.     UNLOCK_MONITOR;
  148.     return;
  149. }
  150.  
  151. /*
  152.  *----------------------------------------------------------------------
  153.  *
  154.  * tick --
  155.  *
  156.  *      If any processes are scheduled for profiling this routine
  157.  *      is called on each call back timer interrupt.
  158.  *
  159.  * Results:
  160.  *      Always returns SUCCESS.
  161.  * 
  162.  * Side effects:
  163.  *
  164.  *      If the current process is scheduled for profiling then the 
  165.  *      specialHandling flag is set, and the current PC is recorded in
  166.  *      the process control block.
  167.  *
  168.  *----------------------------------------------------------------------
  169.  */ 
  170.  
  171. /*ARGSUSED*/
  172. static void
  173. tick(time, clientData)
  174.     Timer_Ticks time;
  175.     ClientData clientData;
  176. {
  177.     Proc_ControlBlock *curProcPtr;
  178.  
  179.     assert(clientData == profTimer_QueueElement.clientData);
  180.     if (!mach_KernelMode) {
  181.     assert(profCount);
  182.     curProcPtr = Proc_GetCurrentProc();
  183.     assert(curProcPtr !=  (Proc_ControlBlock *) NIL);
  184.     if (curProcPtr->Prof_Scale >= 2) {
  185.         curProcPtr->specialHandling = TRUE;
  186.     }
  187.     }
  188.     Timer_ScheduleRoutine(&profTimer_QueueElement, TRUE);
  189.     return;
  190. }
  191.  
  192. /*
  193.  *----------------------------------------------------------------------
  194.  *
  195.  * Prof_RecordPC --
  196.  *
  197.  *
  198.  *
  199.  * Results:
  200.  *      None.
  201.  * 
  202.  * Side effects:
  203.  *      None.
  204.  *  
  205.  *----------------------------------------------------------------------
  206.  */ 
  207.  
  208. void
  209. Prof_RecordPC(procPtr)
  210.     Proc_ControlBlock *procPtr;
  211. {
  212.     long pos;
  213.     short *ptr;
  214.     union {
  215.     short shrt;
  216.     char c[2];
  217.     } u;
  218.  
  219.     assert(procPtr->Prof_Scale);
  220.     /*
  221.      * We have to make sure our multiply doesn't overflow
  222.      */
  223.     pos = ((((unsigned long)procPtr->Prof_PC - procPtr->Prof_Offset)>>16) *
  224.         procPtr->Prof_Scale) |
  225.         ((((procPtr->Prof_PC - procPtr->Prof_Offset)&0xFFFF) *
  226.         procPtr->Prof_Scale) >> 16);
  227.  
  228.     ptr = &procPtr->Prof_Buffer[pos/sizeof(*ptr)];
  229.     /*
  230.      * Make sure the pointer is in the proper range.
  231.      */
  232.     if (ptr < procPtr->Prof_Buffer || ptr >=
  233.         &procPtr->Prof_Buffer[procPtr->Prof_BufferSize/sizeof(short)]) {
  234.     procPtr->Prof_PC = 0;
  235.     return;
  236.     }
  237.     /*
  238.      * Copy the counter in, increment it, and copy it back out.
  239.      */
  240.     if (Vm_CopyInProc(sizeof(short), procPtr, (Address) ptr, u.c, 1)
  241.       != SUCCESS) {
  242.     Prof_Disable(procPtr);
  243.     return;
  244.     }
  245.     ++u.shrt;
  246.     if (Vm_CopyOutProc(sizeof(short), u.c, 1, procPtr, (Address) ptr)
  247.       != SUCCESS) {
  248.     Prof_Disable(procPtr);
  249.     return;
  250.     }
  251.     procPtr->Prof_PC = 0;
  252.     return;
  253. }
  254.  
  255.  
  256. /*
  257.  *----------------------------------------------------------------------
  258.  *
  259.  * Prof_Disable --
  260.  *
  261.  *    Disable profiling of a process.
  262.  *
  263.  * Results:
  264.  *    None.
  265.  *
  266.  * Side effects:
  267.  *      Clears the Prof_Scale and Prof_PC fields of the PCB, and decrements
  268.  *      the count of profiled processes.  If no other processes are being
  269.  *      profiled, removes the profil timer from the callback timer queue.
  270.  *
  271.  *----------------------------------------------------------------------
  272.  */
  273.  
  274. void
  275. Prof_Disable(procPtr)
  276.     Proc_ControlBlock *procPtr;
  277. {
  278.     LOCK_MONITOR;
  279.     if (procPtr->Prof_Scale != 0) {
  280.     assert(profCount > 0);
  281.     procPtr->Prof_Scale = 0;
  282.     procPtr->Prof_PC = 0;
  283.     --profCount;
  284.     if (profCount == 0) {
  285.         Timer_DescheduleRoutine(&profTimer_QueueElement);
  286.     }
  287.     }
  288.     UNLOCK_MONITOR;
  289.     return;
  290. }
  291.  
  292.